package
{
	public class World
	{
		private var lifes:Vector.<Boolean>;
		private var tempLifes:Vector.<Boolean>;
		public var rows:int = 100;
		public var columns:int = 100;
		private var numbers:uint;
		private var generation:uint;
		
		public function World()
		{
			//initialise world
			numbers = rows*columns;
			lifes = new Vector.<Boolean>(numbers);
			tempLifes = new Vector.<Boolean>(numbers);
			clearWorld();
		}
		
		public function worldSize():uint
		{
			return numbers;
		}
		
		public function SetLifeState(cRow:int, cColumn:int, state:Boolean):void
		{
			lifes[cRow*columns+cColumn] = state;
		}
		
		public function lifeState(cRow:int, cColumn:int):Boolean
		{
			return lifes[cRow*columns+cColumn];
		}
		
		public function UpdateWorld():void
		{
			//update the lifes in world by rules.
			//rule: Each cell is surrounded by eight cells
			//1: 2 near cells are alive, this cell remain.
			//2: 3 near cells are alive, this cell alive. (if current state is dead, turn it to alive)
			//3: other situation, this cell dead.
			
			var i:int;
			var row:int, column:int;
			var nearRow:int, nearColumn:int;
			var aliveNumber:uint;
			for(i=0; i<numbers; i++)
			{
				//check eight surrounded cells;
				row = i/columns;
				column = i%columns;
				
				aliveNumber = 0;
				
				if(row!=0 && row!=rows-1 && column!=0 && column!=columns-1)
				{
//					var upI:int = i-columns;
//					var downI:int = i+columns;
					aliveNumber = lifes[i-columns-1]+lifes[i-columns]+lifes[i-columns+1]+lifes[i-1]+lifes[i+1]
						+lifes[i+columns-1]+lifes[i+columns]+lifes[i+columns+1];
				}
				else
				{
					nearRow = row-1;
					//top left
					if(row == 0)
						nearRow = rows-1;
					if(column == 0)
						nearColumn = columns-1;
					else
						nearColumn = column-1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//top middle
					nearColumn = column;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//top right
					if(column == columns-1)
						nearColumn = 0;
					else
						nearColumn = column+1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//left
					nearRow = row;
					if(column == 0)
						nearColumn = columns-1;
					else
						nearColumn = column-1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//right
					if(column == columns-1)
						nearColumn = 0;
					else
						nearColumn = column+1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//down left
					nearRow = row+1;
					if(row == rows-1)
						nearRow = 0;
					if(column == 0)
						nearColumn = columns-1;
					else
						nearColumn = column-1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//down middle
					nearColumn = column;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
					//down right
					if(column == columns-1)
						nearColumn = 0;
					else
						nearColumn = column+1;
					if(lifeState(nearRow, nearColumn) == true)
						aliveNumber++;
				}
				// judge this cell
				if(aliveNumber == 2)
					tempLifes[i] = lifes[i];
				else if(aliveNumber == 3)
					tempLifes[i] = true;
				else
					tempLifes[i] = false;
			}
			
			for(i=0; i<numbers; i++)
				lifes[i] = tempLifes[i];
			
			generation ++;
		}
		
		public function randomWorld():void
		{
			var i:int;
			for(i=0; i<numbers; i++)
			{
				lifes[i] = (Math.random() < 0.30);
//				var randNum:Number = Math.random();
//				if(randNum < 0.5)
//					lifes[i] = false;
//				else
//					lifes[i] = true;
			}
			generation = 0;
		}
		
		public function clearWorld():void
		{
			var i:int;
			for(i=0; i<numbers; i++)
				lifes[i] = false;
			generation = 0;
		}
		
		public function lifeGeneration():uint
		{
			return generation;
		}
		
		public function resizeWorld(width:int, height:int):void
		{
			columns = width;
			rows = height;
			numbers = rows*columns;
			lifes = null;
			tempLifes = null;
			lifes = new Vector.<Boolean>(numbers);
			tempLifes = new Vector.<Boolean>(numbers);
			clearWorld();
		}
	}
}